﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Channels;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using WindowsFormsApp1.Test;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        [DllImport("Dll1.dll")]
        public extern static void releasRoom();
        [DllImport("Dll1.dll")]
        public extern static IntPtr runCV2(ref int width, ref int height, ref int channel,IntPtr path);
        private void runCV_Click(object sender, EventArgs e)
        {
            runOpencv();
        }
        private void runOpencv(string path= "Setting\\template.jpg")
        {
            int width = 0, height = 0, channels = 0, step = 0, strid = 0;
            IntPtr ptr = IntPtr.Zero;
            try
            {
                ptr = runCV2(ref width, ref height, ref channels, Marshal.StringToHGlobalAnsi(path));
            }
            catch (Exception exp)
            {
                MessageBox.Show(exp.Message);
                return;
            }

            if (ptr != null)
            {
                PixelFormat format = new PixelFormat();
                switch (channels)
                {
                    case 1:
                        format = PixelFormat.Format8bppIndexed;
                        break;
                    case 3:
                        format = PixelFormat.Format24bppRgb;
                        break;
                    case 4:
                        format = PixelFormat.Format32bppArgb;
                        break;
                    default:
                        throw new Exception("channels error!");
                }
                strid = (width * channels + 3) / 4 * 4;//((src.Width * ch) + 3) / 4 * 4       
                Bitmap bmpCV = new Bitmap(width, height, strid, format, ptr);
                Bitmap bmp = bmpCV.Clone(new Rectangle(0, 0, width, height), format);
                Image img = Image.FromHbitmap(bmp.GetHbitmap());
                releasRoom();
                pb.Invoke(new Action(() =>
                {
                    pb.Image = img;
                }));
            }
        }
        private void arrayToBmp(in IntPtr ptr, in int channels, in int width, in int height, out Bitmap bmp)
        {
            if (ptr == null)
            {
                bmp = null;
                return;
            }

            PixelFormat format = new PixelFormat();
            switch (channels)
            {
                case 1:
                    format = PixelFormat.Format8bppIndexed;
                    break;
                case 3:
                    format = PixelFormat.Format24bppRgb;
                    break;
                case 4:
                    format = PixelFormat.Format32bppArgb;
                    break;
                default:
                    throw new Exception("channels error!");
            }
            int strid = (width * channels + 3) / 4 * 4;//((src.Width * ch) + 3) / 4 * 4
                                                       //Bitmap bmpCV = new Bitmap(width,height,strid,format,ptr);
                                                       //Bitmap bmp = bmpCV.Clone(new Rectangle(0, 0, width, height), format);                
                                                       //byte[] dst = new byte[strid*channels*height];
            int totalPixel = width * height * 3;
            int[] src = new int[totalPixel];
            int[][] dst = new int[height][];
            Marshal.Copy(ptr, src, 0, totalPixel);
            for (int i=0;i<height;i++)
            {
            //    Marshal.Copy(ptr, i * width * 3,, i * width * 3);
            //    Array.Copy(,,,);
            }


            Bitmap bmpCV = new Bitmap(width, height, strid, format, ptr);
            bmp = bmpCV.Clone(new Rectangle(0, 0, width, height), format);
        }

        private void setTarget_Click(object sender, EventArgs e)
        {
            SetTargetForm stForm = new SetTargetForm();
            stForm.SAVE_EVENT += getSettingFormParam;
            stForm.ShowDialog();
        }
        private void getSettingFormParam(Image img,params Rectangle[] rectangles)
        {
            //MessageBox.Show(rectangles.Length.ToString());
        }

        string[] pathArray;//文件集合
        int index=0;//记录第几个文件
        private void Next_bt_Click(object sender, EventArgs e)
        {
            if(pathArray==null)
            {
                MessageBox.Show("directory is null !");
                return;
            }
            else
            {
                if(index>=pathArray.Length)
                {
                    MessageBox.Show("Last one");
                    index = 0;
                    return;
                }
                if (isCorrectFile(pathArray[index],"jpg","bmp","jpeg"))
                {
                    runOpencv(pathArray[index]);
                }
            }
            index++;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName">包含路径的文件名</param>
        /// <returns></returns>
        bool isCorrectFile(string fileName,params string[] targets)
        {
            string[] array = fileName.Split('\\');
            foreach(string str in targets)
            {
                if(array[array.Length - 1].Contains(str))
                {
                    return true;
                }
            }
            return false;
        }

        private void setPicDir_bt_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowser = new FolderBrowserDialog();
            if(folderBrowser.ShowDialog()==DialogResult.OK)
            {
                pathArray = Directory.GetFiles(folderBrowser.SelectedPath);
                index = 0;
            }
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            pb.Size = new Size(this.Size.Width-runCV.Width-50,this.Height-50);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            pb.Size = new Size(this.Size.Width - runCV.Width - 50, this.Height - 50);
        }

        List<PointF> points = new List<PointF>();
        List<PointF[]> lines = new List<PointF[]>();
        private void pb_Paint(object sender, PaintEventArgs e)
        {
            Pen blue_pen = new Pen(Color.Green,3.0f);
            Brush brush = Brushes.Blue;
            float circleRadiom = 5.0f;

            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            if (lines != null)
            {
                foreach (PointF[] line in lines)
                {
                    e.Graphics.DrawLine(blue_pen, line[0], line[1]);
                }
            }
            if (points != null)
            {
                foreach (PointF p in points)
                {
                    e.Graphics.FillEllipse(brush, circle2rectangle(p,circleRadiom));
                }
            }
        }
        private RectangleF circle2rectangle(PointF p,float r)
        {
            PointF topleft = new PointF();
            topleft.X = p.X - r;
            topleft.Y = p.Y - r;
            return new RectangleF(topleft, new SizeF(r * 2, r * 2));
        }

        private void Test_bt_Click(object sender, EventArgs e)
        {
            #region 坐标变换
            PointF origine_p = new PointF(200.0f,200.0f);
            PointF start_p = new PointF(200.0f,300.0f);
            lines.Add(new PointF[] { origine_p, start_p });
            MyNumerics numerics = new MyNumerics();
            float ag =90f;
            lines.Add(new PointF[] { origine_p, numerics.rotate(ag, in start_p, origine_p) });

            points.Add(origine_p);
            points.Add(start_p);
            points.Add(numerics.rotate(ag, in start_p, origine_p));

            points.Add(numerics.moveByAngle(100f, 60f, start_p));
            lines.Add(new PointF[] { numerics.moveByAngle(100f, 60f, start_p), start_p });

            pb.Invalidate();
            #endregion

            Test.NumericsTest n = new NumericsTest();
            n.run();
        }
    }
}